package for_all;

// -----------------------------------------------------------------------------
// Importanweisungen
import chat_client.ClientGui;
import java.awt.Frame;
import java.io.*;
import java.net.*;

public class Transporter implements Serializable {
    
    // -------------------------------------------------------------------------
    // Variablendeklarationen
    private DataOutputStream out;
    private DataInputStream in;
    private ObjectOutputStream oout;
    private ObjectInputStream oin;
    private boolean status;
    private PopUp fail;
    private Frame frame;
    
    
    // -------------------------------------------------------------------------
    // Kostruktor #1: Client (für gegebenen Port und Host, clientGUI)
    public Transporter(int port, String host, ClientGui clientGui) {
        
        // ClientGui setzen
        this.frame = clientGui;
        
        // 3 * versuchen eine Verbindung zum Server aufzubauen
        for (int i = 0; (i < 3) && (!this.status) ; i++) {
            
            try {   
                this.connect(new Socket(host, port));
            } catch (UnknownHostException ex) {
                //fail = new PopUp(frame, "Der Host wurde nicht gefunden", "Kein Host", PopUp.MessageTyp.Error);
            } catch (IOException ex) {
                //fail = new PopUp(frame, "IOException: " + ex.getMessage(), "Fehler im Konstruktor des Transporters", PopUp.MessageTyp.Error);
            } 
        }
        
        // Felermeldung, wenn keine Verbindung hergestellt werden konnte
        if (!this.status) {
            this.fail = new PopUp(this.frame, "Es konnte kein Server gefunden werden!\nBitte versuchen Sie es später erneut.", "Keine Verbindung", PopUp.MessageTyp.Error);
        }  
    }
    
    
    // -------------------------------------------------------------------------
    // Konstruktor #2: Server (für gegebenen Socket)
    public Transporter (Socket so) {
        // Verbindung aufbauen
        this.connect(so);
    }
    
    
    // -------------------------------------------------------------------------
    // Verbindung zum Server aufbauen
    private boolean connect (Socket socket) {
        
        try {                               // unknownHost, IOExecption abfangen

            this.out    = new DataOutputStream(socket.getOutputStream());
            this.in     = new DataInputStream(socket.getInputStream());
            this.oout   = new ObjectOutputStream(this.out);
            this.oin    = new ObjectInputStream(this.in);
            
        } catch (UnknownHostException ex) {
            
            this.status = false;
            return false;
            
        } catch (IOException ex) {
            
            this.status = false;
            return false;
        }
        
        this.status = true;
        return true;
        
    }
    
    
    // -------------------------------------------------------------------------
    // Senden eines Objektes an den Server/Client
    public void sendObject(Object object) {
        
        if (this.isConnected()) {
            
            try {
                oout.writeObject(object);
                oout.flush();
            } catch (IOException ex) {
                if (this.frame != null) {
                    this.fail = new PopUp(frame, "IOException :: " + ex.getMessage(), "Fehler in sendObject", PopUp.MessageTyp.Error);
                }
            }
        }  
    }
    
    
    // -------------------------------------------------------------------------
    // Reseten des OOUT
    public void reset () {
        try {
            this.oout.reset();
        } catch (IOException ex) {
            fail = new PopUp(frame, "IOException: " + ex.getMessage(), "Fehler in reset des Transporters", PopUp.MessageTyp.Error);
        }
    }
    
    
    // -------------------------------------------------------------------------
    // Empfangen eines Objektes vom Server
    public Object receiveObject() {
        
            try {
                return oin.readObject();
            } catch (IOException | ClassNotFoundException | NullPointerException ex) {
                if (this.frame != null) {
                    this.fail = new PopUp(frame, "IOExcpetion: " + ex.getMessage(), "Fehler in receiveObject", PopUp.MessageTyp.Error);
                }
                return null;
            }

    }
    
    
    // -------------------------------------------------------------------------
    // Überprüfen, ob eine Verbindung zum Server besteht
    public final boolean isConnected() {
        
        return this.status;
    
    }
    
    
    // -------------------------------------------------------------------------
    // Frame für Transporter setzen
    public void setFrame(Frame fr) {
        
        this.frame = fr;
        
    }
        
    // -------------------------------------------------------------------------
    // schließen aller Verbindungen
    public void close() {
        
        try {
            this.oin.close();
            this.in.close();
            this.out.close();
            this.oout.close();
        } catch (IOException ex) {
            this.fail = new PopUp(frame, "IOException: " + ex.getMessage(), "Fehler in Close des Transporters", PopUp.MessageTyp.Error);
        }
        
    }   
}